package com.huiminpay.transaction.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huiminpay.merchant.api.AppService;
import com.huiminpay.merchant.api.MerchantService;
import com.huiminpay.merchant.common.cache.domain.BusinessException;
import com.huiminpay.merchant.common.cache.domain.CommonErrorCode;
import com.huiminpay.merchant.common.cache.util.AmountUtil;
import com.huiminpay.merchant.common.cache.util.EncryptUtil;
import com.huiminpay.merchant.common.cache.util.PaymentUtil;
import com.huiminpay.paymentagent.api.PayChannelAgentService;
import com.huiminpay.paymentagent.api.conf.AliConfigParam;
import com.huiminpay.paymentagent.api.dto.AlipayBean;
import com.huiminpay.paymentagent.api.dto.PaymentResponseDTO;
import com.huiminpay.transaction.api.PayChannelService;
import com.huiminpay.transaction.api.TransactionService;
import com.huiminpay.transaction.convert.PayOrderConvert;
import com.huiminpay.transaction.dto.PayChannelParamDTO;
import com.huiminpay.transaction.dto.PayOrderDTO;
import com.huiminpay.transaction.dto.QRCodeDto;
import com.huiminpay.transaction.entity.PayOrder;
import com.huiminpay.transaction.mapper.PayOrderMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

@Slf4j
@Service
public class TransactionServiceImpl implements TransactionService {
    // 支付入口url
    @Value("${huiminpay.payurl}")
    private String payurl;

    @Reference
    MerchantService merchantService;

    @Reference
    AppService appService;
    @Autowired
    PayChannelService payChannelService;
    @Reference
    PayChannelAgentService payChannelAgentService;
    @Autowired
    PayOrderMapper payOrderMapper;

    @Override
    public String createStoreQRCode(QRCodeDto qrCodeDto) throws BusinessException {
        //获取参数
        Long merchantId = qrCodeDto.getMerchantId();
        String appId = qrCodeDto.getAppId();
        Long storeId = qrCodeDto.getStoreId();
        //判断应用是否属于当前商户
        Boolean appcontains = appService.queryAppInMerchant(appId, merchantId);
        if (!appcontains) {
            throw new BusinessException(CommonErrorCode.E_200005);
        }
        //判断门店是否属于当前商户
        Boolean storecontains = merchantService.queryStoreInMerchant(storeId, merchantId);
        if (!storecontains) {
            throw new BusinessException(CommonErrorCode.E_200006);
        }
        //1. 生成支付信息
        PayOrderDTO payOrderDTO = new PayOrderDTO();
        payOrderDTO.setMerchantId(qrCodeDto.getMerchantId());
        payOrderDTO.setAppId(qrCodeDto.getAppId());
        payOrderDTO.setStoreId(qrCodeDto.getStoreId());
        payOrderDTO.setSubject(qrCodeDto.getSubject());//显示订单标题
        payOrderDTO.setChannel("huimin_c2b");//服务类型
        payOrderDTO.setBody(qrCodeDto.getBody());//订单内容
        String jsonString = JSON.toJSONString(payOrderDTO);
        log.info("transaction service createStoreQRCode,JsonString is {}",jsonString);

        // 将支付信息保存到票据中
        String ticket = EncryptUtil.encodeUTF8StringBase64(jsonString);
        //支付入口
        String payEntryUrl = payurl +ticket;
        log.info("transaction service createStoreQRCode,pay‐entry is {}",payEntryUrl);
        return payEntryUrl;

    }

    // 支付宝订单保存
    @Override
    public PaymentResponseDTO submitOrderByAli(PayOrderDTO payOrderDTO) throws BusinessException {
        //将订单信息插入数据库中(pay_order表)
        payOrderDTO =  save(payOrderDTO);
        //调用支付渠道代理接口完成支付
        PaymentResponseDTO paymentResponseDTO = alipayH5(payOrderDTO.getTradeNo());
        return paymentResponseDTO;
    }

    // 调用支付渠道代理接口实现支付
    private PaymentResponseDTO alipayH5(String tradeNo) throws BusinessException{
        //configParam,alipayBean//一个是支付渠道参数，一个是支付实体
        //构建支付实体
        AlipayBean alipayBean = new AlipayBean();
        alipayBean.setOutTradeNo(tradeNo); //设置订单编号
        //根据tradeNo查询订单信息
        PayOrder payOrder = queryPayOrder(tradeNo);
        if(payOrder==null){
            throw new BusinessException(CommonErrorCode.E_200018);
        }
        alipayBean.setSubject(payOrder.getSubject()); //订单标题
        alipayBean.setBody(payOrder.getBody()); //订单描述
        alipayBean.setStoreId(payOrder.getStoreId()); //设置门店id
        //数据库中的订单金额单位为分，需要转换为元
        try {
            String yuanStr = AmountUtil.changeF2Y(payOrder.getTotalAmount().toString());
            alipayBean.setTotalAmount(yuanStr);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        alipayBean.setExpireTime("30m"); //设置过期时间
        //获取支付渠道参数
        PayChannelParamDTO payChannelParamDTO = payChannelService.queryParamByAppPlatformAndPayChannel(payOrder.getAppId(), payOrder.getChannel(), payOrder.getPayChannel());
        if(payChannelParamDTO==null){
            throw new BusinessException(CommonErrorCode.E_300007);
        }
        //获取的是json格式的字符串，需要转换为对象
        String paramJson = payChannelParamDTO.getParam();//获取支付渠道参数
        AliConfigParam configParam = JSON.parseObject(paramJson, AliConfigParam.class);
        //AliConfigParam aliConfigParam, AlipayBean alipayBean
        PaymentResponseDTO payOrderByAliWAP = payChannelAgentService.createPayOrderByAliWAP(configParam,alipayBean);
        return payOrderByAliWAP;
    }

    // 根据订单编号查询订单详情
    private PayOrder queryPayOrder(String tradeNo) {
        return  payOrderMapper.selectOne(new LambdaQueryWrapper<PayOrder>().eq(PayOrder::getTradeNo,tradeNo));
    }

    // 将订单信息保持到数据库中
    private PayOrderDTO save(PayOrderDTO payOrderDTO) {
        //将dto转换为entity
        PayOrder payOrder = PayOrderConvert.INSTANCE.dto2entity(payOrderDTO);
        //补全数据
        String tradeNo = PaymentUtil.genUniquePayOrderNo(); //采用雪花算法生成订单号
        payOrder.setTradeNo(tradeNo); //订单号
        payOrder.setPayChannel("ALIPAY_WAP"); //支付渠道编码
        payOrder.setCurrency("CNY"); //币种
        payOrder.setTradeState("0");//订单状态
        payOrder.setCreateTime(LocalDateTime.now());//创建时间
        payOrder.setExpireTime(LocalDateTime.now().plus(30, ChronoUnit.MINUTES)); //有效时间
        payOrderMapper.insert(payOrder);
        return PayOrderConvert.INSTANCE.entity2dto(payOrder);
    }
}
